#!/usr/bin/env python

# elliptical_chuck_graph.py

from __future__ import division

import math

from ot_simulator import graph

Max_dimensions = 600

def to_cartesian(r, theta):
    return r * math.cos(theta), r * math.sin(theta)

def ellipse(center, angle, semi_major, semi_minor):
    r'''Generates an ellipse in polar coordinates.

    `center` is polar, `angle` is in radians.

    From wikipedia: http://en.wikipedia.org/wiki/Ellipse#General_polar_form
    '''
    r_center, theta_center = center
    for theta_deg in range(0, 360):
        theta = math.radians(theta_deg)
        P = r_center * ((semi_minor**2 - semi_major**2)
                          * math.cos(theta + theta_center - 2*angle)
                        + (semi_major**2 + semi_minor**2)
                          * math.cos(theta - theta_center))
        R = (semi_minor**2 - semi_major**2) * math.cos(2*theta - 2*angle) \
            + semi_major**2 + semi_minor**2
        Q = math.sqrt(2) * semi_major * semi_minor * \
              math.sqrt(R - 2 * r_center**2 * math.sin(theta - theta_center)**2)
        yield (P + Q) / R, theta

def circle(center, radius):
    r'''Generates an circle in cartesian coordinates.

    `center` is cartesian.
    '''
    x_center, y_center = center
    for theta_deg in range(0, 180):
        theta = math.radians(theta_deg)
        yield (x_center + radius * math.cos(theta),
               y_center + radius * math.sin(theta))

def run(e, sr):
    semi_major = e + sr
    semi_minor = sr
    g = graph.graph(Max_dimensions)
    #g.line((-semi_minor, -semi_major), (-semi_minor, semi_major),
    #       color="rgb(0, 255, 0)")
    g.line((-semi_major, 0), (semi_major, 0), color="rgb(0, 255, 0)")
    g.plot(circle((e/2, 0), e/2), color="rgb(0,0,255)")
    for angle_deg, color \
     in zip((80, 160, 240, 310),
            ("rgb(255, 255, 255)",
             "rgb(0, 255, 255)",
             "rgb(255, 0, 255)",
             "rgb(255, 255, 0)",
    )):
        plot(g, angle_deg, e, semi_major, semi_minor, color)
    g.show()
    #g.write("elliptical_chuck_graph.png")

def plot(graph, angle_deg, e, semi_major, semi_minor, color):
    angle = math.radians(angle_deg)
    c, s = math.cos(angle), math.sin(angle)
    h = e * c
    graph.plot((to_cartesian(r, theta)
                for r, theta
                 in ellipse((h, angle), angle, semi_major, semi_minor)),
               color=color)
    center_x, center_y = to_cartesian(h, angle)
    semi_major_x, semi_major_y = to_cartesian(semi_major, angle)
    semi_minor_x, semi_minor_y = to_cartesian(semi_minor, angle + math.pi/2)
    graph.line((center_x - semi_major_x, center_y - semi_major_y),
               (center_x + semi_major_x, center_y + semi_major_y),
               color)
    graph.line((center_x - semi_minor_x, center_y - semi_minor_y),
               (center_x + semi_minor_x, center_y + semi_minor_y),
               color)
    #tangent = math.atan2(semi_major * s, semi_minor * c)
    tangent = math.atan2(-semi_minor * c, -semi_major * s) + angle
    print >> sys.stderr, "at", angle_deg, "tangent is", math.degrees(tangent)
    ts, tc = math.sin(tangent), math.cos(tangent)
    #b = semi_minor * ts/tc
    if abs(ts) < 1e-4:
        if tc >= 0.0:
            graph.line((-semi_minor, 0), (0, 0), color)
        else:
            graph.line((-semi_minor, 0), (-2*semi_minor, 0), color)
    else:
        graph.line((semi_minor * tc/ts - semi_minor, semi_minor),
                   (-semi_minor * tc/ts - semi_minor, -semi_minor),
                   color)


if __name__ == "__main__":
    import sys
    if len(sys.argv) != 3:
        print >> sys.stderr, "usage: {0} e sr".format(sys.argv[0])
        sys.exit(2)
    run(float(sys.argv[1]), float(sys.argv[2]))
